{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "f9b46d2f-1ea1-4308-b4dc-1f3dd818fda9",
   "metadata": {},
   "source": [
    "# Creating common geometries\n",
    "## Importing sisl\n",
    "\n",
    "Import the `sisl` package and start working with it.  \n",
    "To ensure there is no clashes with other packages we encourage users to stick with the same short-hand name. The `sisl`-developers recommends using `si`. In all of `sisl` documentation it is assumed that `si` refers to `sisl`.\n",
    "\n",
    "An important aspect of `sisl` is the units used:\n",
    "\n",
    "- Ångstrøm [Ang]\n",
    "- Electron volt [eV]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a9f8c081-1548-4247-83d9-82d01f355808",
   "metadata": {},
   "outputs": [],
   "source": [
    "import sisl as si\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1cb92c41-a795-4cf6-93b3-f9e7431a944e",
   "metadata": {},
   "source": [
    "## Creating a geometry\n",
    "\n",
    "`sisl` provides a broad set of methods to create [default geometries](../../api/geom/building.rst). There are `fcc`, `bcc`, `sc`, `graphene` and many other default geometries available.  \n",
    "The default geometry creations are found in the [sisl.geom](../../api/geom/building.rst) module, (for additional details check out ``help(si.geom)``).\n",
    "\n",
    "------\n",
    "\n",
    "Our focus here will be to create an FCC lattice of iron."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "00a3fd65-a0a1-407f-8a69-50a3f53b38b2",
   "metadata": {},
   "outputs": [],
   "source": [
    "iron = si.geom.fcc(2.4, si.Atom(\"Fe\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f582b010-df90-45b4-a765-65ed0ad11c9c",
   "metadata": {},
   "source": [
    "There is lots of information one can retrieve from the geometry, such as:\n",
    "\n",
    "- lattice vectors\n",
    "- number of atoms and orbitals\n",
    "- atomic species\n",
    "\n",
    "Try and extract the above information:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "de0dd680-8c54-4b54-85ce-a9e638a9fc4c",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"All lattice vectors:\")\n",
    "print(iron.lattice.cell)\n",
    "c = iron.lattice.cell[2]\n",
    "print(f\"lattice vector c = {c}\")\n",
    "print(f\"iron has {iron.na} atoms and {iron.no} orbitals\")\n",
    "print(f\"iron's only atom has the atomic number {iron.atoms[0].Z}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "97dd3c7a-fdc2-4098-8200-b4a0f3ccb063",
   "metadata": {},
   "source": [
    "Let us print out the geometry and see for additional information:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "db3f3e59-bbed-4004-8d7f-b8f71b136dbd",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(iron)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "65e15a95-ea3d-4a6f-bce6-539b1f660a7d",
   "metadata": {},
   "source": [
    "This shows a greater detail of the geometry.\n",
    "- it shows there is 1 atom (`na: 1`), and 1 orbital (`no: 1`)\n",
    "- a complete list of atoms (`Atoms{...}`), their atomic number, mass and associated orbitals\n",
    "- the associated `Lattice` object describes the lattice vectors, and which lattice vectors uses periodicity\n",
    "\n",
    "----\n",
    "\n",
    "The geometry also has associated coordinates of the atomic structure, these can be accessed through the `.xyz` attribute:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cde448b3-e410-4a75-b223-6a3a1e3d04f9",
   "metadata": {},
   "outputs": [],
   "source": [
    "iron.xyz"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e8e31626-67f7-4f70-a2a4-1668bc1a3114",
   "metadata": {},
   "source": [
    "In this case there is only 1 atom, and its position is at the origin.\n",
    "\n",
    "Let us try and do a little more complicated structure, say graphene."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b2a42f9d-ee08-4fab-b6d0-c3b460eefb01",
   "metadata": {},
   "outputs": [],
   "source": [
    "graphene = si.geom.graphene()\n",
    "print(graphene)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "186d274a-67b4-406b-a4f5-9f58a9ecc2e5",
   "metadata": {},
   "outputs": [],
   "source": [
    "graphene.xyz"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ba9e548d-96be-4ea9-9e4f-919932a567da",
   "metadata": {},
   "source": [
    "Note how the changed output looks, we now have 2 atoms, but the atom is not duplicated, instead we share a reference (to minimize memory requirement).\n",
    "\n",
    "The atomic coordinates here signals the two positions, and it is obvious that the default bond-length for graphene is defined to be $1.42$."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9aeab656-1f81-44f2-98c9-7cfa4b51391b",
   "metadata": {},
   "source": [
    "#### Other default geometries\n",
    "\n",
    "There are many other implicit geometries available in `sisl` which can be found [here](../../api/geom/building.rst).\n",
    "These can be used to generalize and construct geometries on the fly, in a simply and efficient manner."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "49443b5d-a17b-4643-ba20-f0121c64f773",
   "metadata": {},
   "source": [
    "### Defining atoms\n",
    "\n",
    "The geometries will accept an argument `atoms=` where you can define the atoms in the geometry.\n",
    "We already did this in the `fcc` system where we defined the atom `si.Atom(\"Fe\")`.  \n",
    "Lets delve into the [Atom](../../api/generated/sisl.Atom.rst) object."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "27d9caa7-81c2-4acf-b3a8-ffc93143999b",
   "metadata": {},
   "outputs": [],
   "source": [
    "help(si.Atom)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3539103b-20d6-4ead-8db3-63ddf9044487",
   "metadata": {},
   "source": [
    "Here we create an `fcc` lattice made up of Deuterium atoms"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b3330504-5a71-4609-a8ca-55d70cc0770a",
   "metadata": {},
   "outputs": [],
   "source": [
    "D = si.Atom(1, mass=2.014)\n",
    "fcc_D = si.geom.fcc(1.42, atoms=D)\n",
    "print(fcc_D)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "244c95e7-e4a3-4d5d-9de6-dda2ec6708b7",
   "metadata": {},
   "source": [
    "Another example would be to create a bilayer structure with 2 different atoms (say graphene below hBN)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7cb48c7a-51b7-459c-9627-a03edf2b71d8",
   "metadata": {},
   "outputs": [],
   "source": [
    "C = si.Atom(\"C\")\n",
    "B = si.Atom(\"B\")\n",
    "N = si.Atom(\"N\")\n",
    "hBN = si.geom.bilayer(1.45, bottom_atoms=C, top_atoms=[B, N])\n",
    "print(hBN)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ca3fdf01-537a-4d4a-8a14-cea0f3b12799",
   "metadata": {},
   "source": [
    "This concludes a quick tutorial on how to create a predefined geometry and how to define the atoms in it."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
